package com.seng.resourcetycoon.gui.controllers;

import com.seng.resourcetycoon.factory.TowerFactory;
import com.seng.resourcetycoon.gui.models.ResourceTower;
import com.seng.resourcetycoon.gui.models.Upgrade;
import com.seng.resourcetycoon.gui.views.TowerSetupCellView;
import com.seng.resourcetycoon.manager.GameEnvironment;
import com.seng.resourcetycoon.util.SceneUtil;
import com.seng.resourcetycoon.util.ToastUtil;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import java.math.BigDecimal;
import java.net.URL;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.function.Consumer;

public class MarketController implements Initializable {

    private static final int NUM_TOWERS_TO_POPULATE = 6;
    private static final String UPGRADE_NAME_DEFAULT = "upgrade Coupon";
    private static final BigDecimal DEFAULT_UPGRADE_PRICE = BigDecimal.valueOf(80);

    @FXML
    private ListView<ResourceTower> towerListView;
    @FXML
    private ListView<Upgrade> upgradeListView;
    @FXML
    private Label currencyLabel;
    @FXML
    private Label itemPriceLabel;
    private TowerFactory towerFactory;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        towerFactory = new TowerFactory();
        towerListView.setCellFactory(listView1 -> new TowerSetupCellView());
        populateLists();
        setupSelectionListeners();
        updateCurrencyLabel();
    }

    private void populateLists() {
        ObservableList<ResourceTower> resourceTowers = FXCollections.observableArrayList();
        for (int i = 0; i < NUM_TOWERS_TO_POPULATE; i++) {
            resourceTowers.add(towerFactory.createTower());
        }
        towerListView.setItems(resourceTowers);

        ObservableList<Upgrade> upgrades = FXCollections.observableArrayList(
                new Upgrade(UPGRADE_NAME_DEFAULT, DEFAULT_UPGRADE_PRICE),
                new Upgrade(UPGRADE_NAME_DEFAULT, DEFAULT_UPGRADE_PRICE),
                new Upgrade(UPGRADE_NAME_DEFAULT, DEFAULT_UPGRADE_PRICE)
        );
        upgradeListView.setCellFactory(param -> new ListCell<Upgrade>() {
            @Override
            protected void updateItem(Upgrade item, boolean empty) {
                super.updateItem(item, empty);
                setText(empty || item == null ? null : item.getName());
            }
        });
        upgradeListView.setItems(upgrades);
    }


    private void setupSelectionListeners() {
        towerListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) ->
                Optional.ofNullable(newValue).ifPresent(tower -> itemPriceLabel.setText(tower.getBuyPrice().toPlainString())));

        upgradeListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) ->
                Optional.ofNullable(newValue).ifPresent(upgrade -> itemPriceLabel.setText(upgrade.getBuyPrice().toPlainString())));
    }

    @FXML
    private void handleBuyClick() {
        ResourceTower selectedTower = towerListView.getSelectionModel().getSelectedItem();
        Upgrade selectedUpgrade = upgradeListView.getSelectionModel().getSelectedItem();

        if (selectedTower != null) {
            handlePurchase(selectedTower, GameEnvironment.getInstance()::addTower,towerListView.getItems()::remove);
        } else if (selectedUpgrade != null) {
            handlePurchase(selectedUpgrade, GameEnvironment.getInstance()::addUpgrade,upgradeListView.getItems()::remove);
        } else {
            ToastUtil.showAlert("Must select one", "Error");
        }
        updateCurrencyLabel();
    }

    @FXML
    private void handleBack(){
        SceneUtil.getInstance().closeTmpStage();
    }

    private <T> void handlePurchase(T item, Consumer<T> addToCollection,Consumer<T> removeToCollection) {
        BigDecimal price = (item instanceof ResourceTower) ? ((ResourceTower)item).getBuyPrice() : ((Upgrade)item).getBuyPrice();
        if (GameEnvironment.getInstance().getCoin().compareTo(price) >= 0) {
            GameEnvironment.getInstance().subtractCoin(price);
            addToCollection.accept(item);
            removeToCollection.accept(item);
        } else {
            ToastUtil.showAlert("Money not enough", "Error");
        }
    }

    private void updateCurrencyLabel() {
        currencyLabel.setText("coins: " + GameEnvironment.getInstance().getCoin());
    }
}